package cn.shenlong.util;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import magick.ImageInfo;
import magick.MagickException;
import magick.MagickImage;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Coordinate;
import org.apache.commons.io.FileUtils;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

/**
 * 图片工具类
 * 
 * @author Administrator
 */
public class ImageUtil {

	/**
	 * 添加图片水印
	 * 
	 * @param srcFile
	 * @param destFile
	 * @param minWidth
	 * @param minHeight
	 * @param pos
	 * @param offsetX
	 * @param offsetY
	 * @param markContent
	 * @param markColor
	 * @param markSize
	 * @param alpha
	 * @throws IOException
	 * @throws MagickException
	 */
	public static void waterMarkByImg(File srcFile, File destFile,
			int minWidth, int minHeight, int pos, int offsetX, int offsetY,
			File markFile) throws IOException, MagickException {
		BufferedImage srcImage = ImageIO.read(srcFile);
		int width = srcImage.getWidth();
		int height = srcImage.getHeight();

		BufferedImage markImage = ImageIO.read(markFile);
		int markWidth = markImage.getWidth();
		int markHeight = markImage.getHeight();

		// 如果源图比最小的宽和高还要小或者比水印图片还要小 就不做处理
		if (width < minWidth || height < minHeight || width < markWidth
				|| height < markHeight) {
			srcImage = null;
			if (!srcFile.equals(destFile)) {
				FileUtils.copyFile(srcFile, destFile);
			}
		} else {
			Position p = markPosition(width, height, markWidth, markHeight,
					pos, offsetX, offsetY);
			Thumbnails
					.of(srcFile)
					.size(width, height)
					.watermark(new Coordinate(p.getX(), p.getY()),
							ImageIO.read(markFile), 0.5f).toFile(destFile);

		}
	}

	/**
	 * 添加文字水印
	 * 
	 * @param srcFile
	 *            原始图片文件对象
	 * @param destFile
	 *            目录图片文件对象
	 * @param minWidth
	 *            最小宽度
	 * @param minHeight
	 *            最小高度
	 * @param pos
	 *            位置
	 * @param offsetX
	 *            x坐标
	 * @param offsetY
	 *            y坐标
	 * @param markContent
	 *            水印文字
	 * @param markColor
	 *            水印文字颜色
	 * @param markSize
	 *            字体大小
	 * @param alpha
	 *            透明度
	 * @throws IOException
	 * @throws MagickException
	 */
	public static void waterMarkByTxt(File srcFile, File destFile,
			int minWidth, int minHeight, int pos, int offsetX, int offsetY,
			String markContent, Color markColor, int markSize, int alpha)
			throws IOException, MagickException {
		BufferedImage srcImage = ImageIO.read(srcFile);
		int width = srcImage.getWidth();
		int height = srcImage.getHeight();

		// 字体、字型、字号
		Font f = new Font("宋体", Font.BOLD, 24);
		FontMetrics fm = sun.font.FontDesignMetrics.getMetrics(f);

		// 如果源图比水印图片还要小 就不做处理
		if (width < minWidth || height < minHeight || height < fm.getHeight()
				|| width < fm.stringWidth(markContent)) {
			srcImage = null;
			if (!srcFile.equals(destFile)) {
				FileUtils.copyFile(srcFile, destFile);
			}
		} else {

			// 文字水印图
			BufferedImage bimage = new BufferedImage(
					fm.stringWidth(markContent), fm.getHeight(),
					BufferedImage.TYPE_INT_RGB);
			Graphics2D g2d = bimage.createGraphics();
			// ---------- 增加下面的代码使得背景透明 -----------------
			bimage = g2d.getDeviceConfiguration().createCompatibleImage(width,
					height, Transparency.TRANSLUCENT);
			g2d.dispose();
			g2d = bimage.createGraphics();
			// ---------- 背景透明代码结束 -----------------
			g2d.setColor(markColor);
			g2d.setFont(f); // 字体、字型、字号
			g2d.drawString(markContent, 0, fm.getHeight() / 3 * 2); // 画文字
			g2d.dispose();
			bimage.flush();

			int markWidth = bimage.getWidth();
			int markHeight = bimage.getHeight();

			Position p = markPosition(width, height, markWidth, markHeight,
					pos, offsetX, offsetY);

			Thumbnails
					.of(srcFile)
					.size(width, height)
					.watermark(new Coordinate(p.getX(), p.getY()), bimage, 0.5f)
					.toFile(destFile);
		}
	}

	/**
	 * 添加文字水印
	 * 
	 * @param image
	 *            原始图片对象
	 * @param info
	 *            图片信息
	 * @param width
	 *            最小宽度
	 * @param height
	 *            最高度
	 * @param pos
	 *            位置
	 * @param offsetX
	 *            x坐标
	 * @param offsetY
	 *            y坐标
	 * @param text
	 *            水印文字
	 * @param color
	 *            颜色
	 * @param size
	 *            字体大小
	 * @param alpha
	 *            透明度
	 * @throws MagickException
	 */
	private static void waterMarkByTxt(MagickImage image, ImageInfo info,
			int width, int height, int pos, int offsetX, int offsetY,
			String text, Color color, int size, int alpha)
			throws MagickException {
		/*
		 * Position p = markPosition(width, height, pos, offsetX, offsetY);
		 * DrawInfo draw = new DrawInfo(info); int r = color.getRed(); int g =
		 * color.getGreen(); int b = color.getBlue(); draw.setFill(new
		 * PixelPacket(r * r, g * g, b * b, 65535 - (alpha * 65535 / 100)));
		 * draw.setPointsize(size); draw.setTextAntialias(true);
		 * draw.setText(text); draw.setGeometry("+" + p.getX() + "+" +
		 * p.getY()); image.annotateImage(draw);
		 */
	}

	/**
	 * 图片质量调整
	 * 
	 * @param imgOriginal
	 *            原始图片文件
	 * @param imgNewPath
	 *            图片新路径
	 * @param imgQualityPercent
	 *            图片质量%
	 */
	public static void imageAdjust(File imgOriginal, String imgNewPath,
			Double imgQualityPercent) {
		if (imgOriginal == null || imgNewPath == null
				|| imgNewPath.length() < 1 || imgQualityPercent == null) {
			return;
		}
		try {
			Image imgOri = javax.imageio.ImageIO.read(imgOriginal);
			adjust(imgOri, imgNewPath, imgQualityPercent);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static void adjust(Image imgOri, String imgNewPath,
			Double imgQualityPercent) {

		try {
			// 新图分辨率
			// Integer imgWidthNew = 110;
			// Integer imgHeightNew = 80;
			Integer imgWidthNew = 279;
			Integer imgHeightNew = 200;

			// 重绘
			BufferedImage imgNew = new BufferedImage(imgWidthNew, imgHeightNew,
					BufferedImage.TYPE_INT_RGB);
			imgNew.getGraphics().drawImage(
					imgOri.getScaledInstance(imgWidthNew, imgHeightNew,
							Image.SCALE_SMOOTH), 0, 0, null);

			// 压缩质量
			JPEGEncodeParam param = JPEGCodec.getDefaultJPEGEncodeParam(imgNew);
			param.setQuality(imgQualityPercent.floatValue(), true);

			// 输出到文件流
			FileOutputStream imgNewStream = new FileOutputStream(imgNewPath);
			JPEGImageEncoder imgEncoder = JPEGCodec
					.createJPEGEncoder(imgNewStream);
			imgEncoder.encode(imgNew, param);
			imgNewStream.close();

		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获得水印位置
	 * 
	 * @param width
	 *            原图宽度
	 * @param height
	 *            原图高度
	 * @param p
	 *            水印位置 1-5，其他值为随机。1：左上；2：右上；3：左下；4：右下；5：中央。
	 * @param offsetx
	 *            水平偏移。
	 * @param offsety
	 *            垂直偏移。
	 * @return 水印位置
	 */
	private static Position markPosition(int srcWidth, int srcHeight,
			int markWidth, int markHeight, int p, int offsetx, int offsety) {
		if (p < 1 || p > 5) {
			p = (int) (Math.random() * 5) + 1;
		}
		int x, y;
		switch (p) {
		// 左上
		case 1:

			if (offsetx + markWidth > srcWidth) {
				x = srcWidth - markWidth;
			} else {
				x = offsetx;
			}

			if (offsety + markHeight > srcHeight) {
				y = srcHeight - markHeight;
			} else {
				y = offsety;
			}

			break;
		// 右上
		case 2:

			if (offsetx + markWidth > srcWidth) {
				x = 0;
			} else {
				x = srcWidth - (offsetx + markWidth);
			}

			if (offsety + markHeight > srcHeight) {
				y = srcHeight - markHeight;
			} else {
				y = offsety;
			}
			break;
		// 左下
		case 3:

			if (offsetx + markWidth > srcWidth) {
				x = srcWidth - markWidth;
			} else {
				x = offsetx;
			}

			if (offsety + markHeight > srcHeight) {
				y = srcHeight - markHeight;
			} else {
				y = srcHeight - (offsety + markHeight);
			}

			break;
		// 右下
		case 4:
			if (offsetx + markWidth > srcWidth) {
				x = 0;
			} else {
				x = srcWidth - (offsetx + markWidth);
			}

			if (offsety + markHeight > srcHeight) {
				y = srcHeight - markHeight;
			} else {
				y = srcHeight - (offsety + markHeight);
			}

			break;
		// 中央
		case 5:
			if ((srcWidth / 3) + offsetx > srcWidth) {
				x = srcWidth - offsetx;
			} else {
				x = (srcWidth / 3) + offsetx;
			}

			if (srcHeight / 3 + offsety > srcHeight) {
				y = srcHeight - offsety;
			} else {
				y = srcHeight / 3 + offsety;
			}
			break;
		default:
			throw new RuntimeException("never reach ...");
		}
		return new Position(x, y);
	}

	/**
	 * 水印位置 包含左边偏移量，右边偏移量。
	 * 
	 * @author liufang
	 */
	public static class Position {

		private int x;
		private int y;

		public Position(int x, int y) {
			this.x = x;
			this.y = y;
		}

		public int getX() {
			return x;
		}

		public void setX(int x) {
			this.x = x;
		}

		public int getY() {
			return y;
		}

		public void setY(int y) {
			this.y = y;
		}
	}

	/**
	 * 
	 * @param srcFile
	 * @param width
	 * @param height
	 * @return
	 * @throws IOException
	 * @throws MagickException
	 */
	public static File changeImageSize(File srcFile, int width, int height)
			throws IOException, MagickException {
		BufferedImage srcImage = ImageIO.read(srcFile);
		int orginalWidth = srcImage.getWidth();
		int orginalHeight = srcImage.getHeight();
		// 如果源图比最小的宽和高还要小或者比水印图片还要小 就不做处理
		String tmpPath = System.getProperty("java.io.tmpdir");
		String tmpFileName = String.valueOf(System.currentTimeMillis());
		File tempFile = new File(tmpPath, tmpFileName + ".png");
		tempFile.createNewFile();
		Thumbnails
				.of(srcFile)
				.size(orginalWidth < width ? orginalWidth : width,
						orginalHeight < height ? orginalHeight : height)
				.keepAspectRatio(false).toFile(tempFile);
		return tempFile;
	}

}
